package com.cms.common.model.services.impl;


import com.cms.common.config.LoginKeys;
import com.cms.common.model.criteria.Criteria;
import com.cms.common.model.entity.AdminUser;
import com.cms.common.model.entity.AdminUserRememberLogin;
import com.cms.common.model.entity.Roles;
import com.cms.common.model.repository.AdminUserRememberLoginRepository;
import com.cms.common.model.repository.AdminUserRepository;
import com.cms.common.model.services.AdminUserService;
import com.cms.common.model.vo.RequestData;
import com.cms.common.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.security.NoSuchAlgorithmException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


@Service("AdminUserService")
public class AdminUserServiceImpl implements AdminUserService {

    @Autowired
    AdminUserRepository adminUserRepository;

    @Autowired
    AdminUserRememberLoginRepository adminUserRememberLoginRepository;


    public AdminUser getAdminUserByUsername(String username) {
        return adminUserRepository.findByUsername(username);
    }

    public AdminUser getAdminUserByUuid(String uuid) {
        return adminUserRepository.findByUuid(uuid);
    }

    @Override
    public AdminUser getAdminUserById(Long id) {
        return adminUserRepository.getById(id);
    }

    public String encodePwd(String username, String pwd, String salt) {
        try {
            return MD5Util.MD5Encode(username + pwd + salt);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String token(String key) {
        long time = System.currentTimeMillis();
        try {
            return time + "|" + MD5Util.MD5Encode("" + time + key + time + Math.random());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public AdminUser insertAdminUser(AdminUser adminUser) {
        adminUser = adminUserRepository.saveAndFlush(adminUser);
        return adminUser;
    }

    public String loginToken(String adminUserUuid, String cookieToken) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, 15);
        Date date = calendar.getTime();
        String token = token(adminUserUuid + cookieToken);
        AdminUserRememberLogin adminUserRememberLogin = adminUserRememberLoginRepository.findByCookieToken(cookieToken);
        if (adminUserRememberLogin == null) {
            adminUserRememberLogin = new AdminUserRememberLogin();
            adminUserRememberLogin.setAdminUserUuid(adminUserUuid);
            adminUserRememberLogin.setCookieToken(cookieToken);
        }
        adminUserRememberLogin.setExpireTime(date);
        adminUserRememberLogin.setToken(token);
        adminUserRememberLoginRepository.saveAndFlush(adminUserRememberLogin);
        return token;
    }

    @Override
    public boolean logout(String adminUserUuid, HttpServletRequest request, HttpServletResponse response) {
        AdminUserRememberLogin adminUserRememberLogin = adminUserRememberLoginRepository.findByAdminUserUuid(adminUserUuid);

        Cookie cookie = new Cookie(LoginKeys.rememberLoginCookieKey, null);
        cookie.setMaxAge(0);
        response.addCookie(cookie);

        HttpSession session = request.getSession();
        session.removeAttribute(adminUserRememberLogin.getToken());
        session.removeAttribute(LoginKeys.loginSessionKey);

        request.removeAttribute("adminUser");
        adminUserRememberLoginRepository.delete(adminUserRememberLogin);
        return true;
    }

    public AdminUserRememberLogin getTokenByCookieToken(String cookieToken) {
        AdminUserRememberLogin adminUserRememberLogin = adminUserRememberLoginRepository.findByCookieToken(cookieToken);
        if (adminUserRememberLogin != null && adminUserRememberLogin.getExpireTime().getTime() > System.currentTimeMillis()) {
            return adminUserRememberLogin;
        }
        return null;
    }

    public boolean checkLogin(HttpServletRequest request, HttpServletResponse response) {
        AdminUserRememberLogin adminUserRememberLogin = null;
        HttpSession session = request.getSession();
        String token = (String) session.getAttribute(LoginKeys.loginSessionKey);
        if (token == null) {
            //检测是否有记住登录状态
            String rememberLoginToken = null;
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie c : cookies) {
                    if (LoginKeys.rememberLoginCookieKey.equals(c.getName())) {
                        rememberLoginToken = c.getValue();
                        break;
                    }
                }
            }
            if (rememberLoginToken != null && !rememberLoginToken.equals("")) {
                String[] rememberLoginTokens = rememberLoginToken.split("\\|");
                String uuid = rememberLoginTokens[0];

                //通过 cookie获取登录的对应的token
                adminUserRememberLogin = getTokenByCookieToken(rememberLoginTokens[1] + "|" + rememberLoginTokens[2]);
                if (adminUserRememberLogin == null) {
                    return false;
                }
                if (adminUserRememberLogin.getAdminUserUuid().equals(uuid)) {
                    token = adminUserRememberLogin.getToken();
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
        String[] tokens = token.split("\\|");
        Long time = Long.parseLong(tokens[0]);

        if ((time + 1000 * 60 * 60 * 3) < System.currentTimeMillis()) {//登录状态超过3小时没使用自动下线
            session.removeAttribute(token);
            session.removeAttribute(LoginKeys.loginSessionKey);
            Cookie cookie = new Cookie(LoginKeys.rememberLoginCookieKey, null);
            response.addCookie(cookie);
            return false;
        }


        AdminUser adminUser = (AdminUser) session.getAttribute(token);
        if (adminUser == null) {
            if (adminUserRememberLogin != null) {
                adminUser = getAdminUserByUuid(adminUserRememberLogin.getAdminUserUuid());
            }

        }
        if (adminUser == null) {
            session.removeAttribute(token);
            session.removeAttribute(LoginKeys.loginSessionKey);
            Cookie cookie = new Cookie(LoginKeys.rememberLoginCookieKey, null);
            response.addCookie(cookie);
            return false;
        } else {//执行自动登录功能
            session.setAttribute(LoginKeys.loginSessionKey, token);
            session.setAttribute(token, adminUser);
            request.setAttribute("adminUser", adminUser);
        }
        return true;
    }

    @Override
    public List<AdminUser> findByRoles(Roles roles) {
        return adminUserRepository.findByRoles(roles);
    }

    @Override
    public Page<AdminUser> getAdminUserByPage(RequestData requestData) {
        Criteria<AdminUser> criteria = new Criteria<>();
        requestData.setObjParams(criteria);
        Sort sort = Sort.by(Sort.Order.asc("updateTime"), Sort.Order.asc("id"));
        Pageable pageable = PageRequest.of(requestData.getPage() - 1, requestData.getPageSize(), sort);
        Page<AdminUser> adminUsers = adminUserRepository.findAll(criteria, pageable);
        return adminUsers;
    }

    @Override
    public void deleteUsers(AdminUser adminUser) {
        adminUserRepository.delete(adminUser);
    }
}
